﻿using Blm.Utils.Extensions;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.Configs;
using VisionCloud.Domain.DtoModel.Fms;
using VisionCloud.Domain.DtoModel.Schedule.WorkOrder;
using VisionCloud.Domain.Repository.Interface.Ms;
using VisionCloud.Domain.Repository.Interface.Schedule;
using VisionCloud.Service.Algorithm;
using VisionCloud.Service.Ms;
using VisionCloud.Service.Schedule;
using VisionCloud.Utility;

namespace VisionCloud.Service.Fms
{
    public class UploadService
    {
        public ProjectDCService ProjectDCService { set; get; }
        public AlgorithmService AlgorithmService { set; get; }
        public WorkOrderService WorkOrderService { set; get; }
        public TaskDataUploadService TaskDataUploadService { set; get; }
        public IMsProjectRepository MsProjectRepository { set; get; }
        public IWorkOrderRepository WorkOrderRepository { set; get; }
        public IMsHouseMapBuildingFloorRepository HouseMapBuildingFloorRepository { set; get; }
        private readonly string measuringServicePath = ConfigHelper.GetValue<string>("MeasuringService");
        private readonly string webUrl = ConfigHelper.GetValue<string>("WebUrl");

        /// <summary>
        /// 取minio上的算法json 和 图片文件，拼接后上传到fms
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult> UploadAlgorithmResultToFms(UploadAlgorithmResultToFmsDto request)
        {
            HouseMapBuildingFloorResponseDto fmsProjectInfo = new HouseMapBuildingFloorResponseDto();
            Logger.Info($"UploadAlgorithmResultToFms：{JsonConvert.SerializeObject(request)}");
            try
            {
                string baseDir = measuringServicePath + $"/DataFile/{request.CompanyNo}/{request.ProjectNo}/{request.TaskId}/CFRJ_Result/";
                string urlPath = $"/measuringservice/DataFile/{request.CompanyNo}/{request.ProjectNo}/{request.TaskId}/CFRJ_Result/";
                string staticFileBaseUrl = new Uri(new Uri(webUrl), urlPath).AbsoluteUri;

                fmsProjectInfo = JsonConvert.DeserializeObject<HouseMapBuildingFloorResponseDto>(request.FmsProjectInfo);
                if (fmsProjectInfo == null || string.IsNullOrWhiteSpace(fmsProjectInfo.UploadVersion))
                {
                    return ApiResult.Error("版本号不合法");
                }
                try
                {
                    TaskDataUploadService.UploadTableFromDataset(request.TaskDataset, request.DeviceNo, baseDir);
                }
                catch (Exception ex)
                {
                    Logger.Error($"同步任务数据错误，请求参数{request.ToJsonStr()}", ex);
                    return ApiResult.Error("同步任务数据错误");
                }
                string bimMapCode = $"{fmsProjectInfo.ProjectCode}-{fmsProjectInfo.BuildingCode}-{fmsProjectInfo.FloorCode}";
                List<GetWorkOrderListWithProjectInfoRspDto> workOrderList = new List<GetWorkOrderListWithProjectInfoRspDto>();
                if (fmsProjectInfo.SelectedWorkOrders?.Count > 0)
                {
                    workOrderList = WorkOrderRepository
                        .WhereAsNoTracking(x => fmsProjectInfo.SelectedWorkOrders.Contains(x.BpsTaskId))
                        .Select(x => new GetWorkOrderListWithProjectInfoRspDto
                        {
                            BpsTaskId = x.BpsTaskId,
                            ProcedureCode = x.ProcedureCode,
                            WorkOrderId = x.Id
                        }).ToList();
                }
                if (workOrderList != null && workOrderList.Count > 1)
                {
                    if (workOrderList.Count(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.天花)) > 1
                        || workOrderList.Count(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.螺杆洞)) > 1
                        || workOrderList.Count(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.内墙)) > 1)
                    {
                        return ApiResult.Error("同类型机器人工单不允许多选");
                    }
                }
                if (request.RobotCategoryList.Contains(WorkOrderTaskTypeEnum.天花.ToString()))
                {
                    string url = baseDir + "CeilResult/3Dceil.json";
                    if (!File.Exists(url))
                    {
                        return ApiResult.Error("天花结果文件不存在");
                    }
                    var rspStr = await FileInfoUtils.ReadFileToStringAsync(url, Encoding.UTF8);
                    var rspObj = JsonConvert.DeserializeObject<Ceiling3DJsonResult>(rspStr);
                    var tempRsp = await ProjectDCService.CeilingPolishListSpaceCeiling(new WdcBaseRqDto
                    {
                        Version = fmsProjectInfo.UploadVersion,
                        BimMapCode = bimMapCode
                    });
                    if (tempRsp == null || tempRsp.Data == null)
                    {
                        return ApiResult.Error($"项目{bimMapCode}天花模型不存在,请联系FMS");
                    }

                    if (tempRsp.Data.RoomList == null || tempRsp.Data.RoomList.Count == 0)
                    {
                        return ApiResult.Error($"项目{bimMapCode}天花边界不存在,请联系FMS");
                    }

                    if (rspObj == null)
                    {
                        return ApiResult.Error("天花结果内容不正确");
                    }

                    string saveFilePath1 = baseDir + "CeilResult/temp.json";
                    FileInfoUtils.SaveJsonFile(JsonConvert.SerializeObject(tempRsp), saveFilePath1);
                    bool needUpdateTemp = AlgorithmService.IsJsonModify(tempRsp.Data);
                    if (needUpdateTemp)
                    {
                        SaveFloorRoomSettingsRqDto saveFloorRoomSettingsRq = new SaveFloorRoomSettingsRqDto
                        {
                            BimMapCode = bimMapCode,
                            Version = tempRsp.Data?.Version,
                            RoomSettings = tempRsp.Data?.RoomSettings
                        };
                        var saveRsp = await ProjectDCService.SaveFloorRoomSettings(saveFloorRoomSettingsRq);
                        if (saveRsp?.Code != 0)
                        {
                            // 更新模型失败
                            return ApiResult.Error($"项目{bimMapCode}天花边保存失败,请联系FMS");
                        }
                        tempRsp = await ProjectDCService.CeilingPolishListSpaceCeiling(new WdcBaseRqDto
                        {
                            BimMapCode = bimMapCode,
                            Version = fmsProjectInfo.UploadVersion
                        });
                    }
                    tempRsp.Data.BimMapCode = bimMapCode;
                    tempRsp.Data.Remark = "CeLiangRobot";
                    tempRsp.Data.IsVisionData = true;
                    var rq = tempRsp.Data;
                    bool setResult = AlgorithmService.SetBoundaryforCeilingResult(rq, rspObj, new SetBoundaryforCeilingParam
                    {
                        CeilingBaseDir = baseDir,
                        StaticFileBaseUrl = staticFileBaseUrl,
                        NeedDeelCeiling = fmsProjectInfo.NeedDeelCeiling
                    });
                    rq.Version = fmsProjectInfo.UploadVersion;
                    // 保存输出文件
                    string saveFilePath = baseDir + "CeilResult/output.json";
                    FileInfoUtils.SaveJsonFile(JsonConvert.SerializeObject(rq), saveFilePath);
                    // 上传工单信息
                    var ceilingOrder = workOrderList.FirstOrDefault(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.天花));
                    if (ceilingOrder != null)
                    {
                        var workOrder = WorkOrderService.GetWorkOrder(ceilingOrder.BpsTaskId);
                        if (workOrder == null)
                        {
                            return ApiResult.Error("天花工单不存在");
                        }
                        var rqDto = new UploadRequestDto
                        {
                            BpsTaskId = ceilingOrder.BpsTaskId,
                            StartTime = DateTime.Now,
                            EndTime = DateTime.Now,
                            JsonFile = staticFileBaseUrl + "CeilResult/output.json",
                            RobotCode = workOrder.ProcedureCode,
                            Version = fmsProjectInfo.UploadVersion,
                            Remark = "测量机器人上传",
                            Status = fmsProjectInfo.WorkOrderStatus
                        };
                        var uploadResult = await WorkOrderService.Upload(rqDto);
                        if (uploadResult.Code != AjaxCode.Success)
                        {
                            Logger.Error($"UploadAlgorithmResultToFms：{JsonConvert.SerializeObject(rqDto)} {uploadResult.Message}");
                            return ApiResult.Error($"上传天花工单失败，详细信息：{uploadResult.Message}");
                        }
                    }
                    else // 无工单则自己上传机器人数据
                    {
                        var fmsRsp = await ProjectDCService.SaveCeilingPolishFloor(rq);
                        if (fmsRsp == null || fmsRsp.Code != 0)
                        {
                            return ApiResult.Error($"上传天花工单失败，详细信息：{fmsRsp?.Message}");
                        }
                    }
                }
                if (request.RobotCategoryList.Contains(WorkOrderTaskTypeEnum.内墙.ToString()))
                {
                    string url = baseDir + "InnerWallResult/json_FMS/allJson.json";
                    if (!File.Exists(url))
                    {
                        return ApiResult.Error($"allJson文件不存在");
                    }
                    var rspStr = await FileInfoUtils.ReadFileToStringAsync(url, Encoding.UTF8);
                    var rq = JsonConvert.DeserializeObject<SaveInnerWallVisionCollectRqDto>(rspStr);
                    string jpgUrl = staticFileBaseUrl + "InnerWallResult/json_FMS/";
                    rq.Data?.ForEach(d =>
                    {
                        if (!string.IsNullOrEmpty(d.VisionWallImage?.Url))
                        {
                            string jpgFileName = d.VisionWallImage.Url.Split("/").ToList().LastOrDefault();
                            d.VisionWallImage.Url = jpgUrl + jpgFileName;
                        }
                        if (!string.IsNullOrEmpty(d.Url))
                        {
                            string jpgFileName = d.Url.Split("/").ToList().LastOrDefault();
                            d.Url = jpgUrl + jpgFileName;
                        }
                    });
                    rq.BimMapCode = bimMapCode;
                    rq.Version = fmsProjectInfo.UploadVersion;
                    // 保存输出文件
                    string saveFilePath = baseDir + "InnerWallResult/json_FMS/output.json";
                    FileInfoUtils.SaveJsonFile(JsonConvert.SerializeObject(rq), saveFilePath);
                    // 上传工单信息
                    var innerWallOrder = workOrderList.FirstOrDefault(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.内墙));
                    if (innerWallOrder != null && request.InnerWallVersion == "1.3")
                    {
                        var workOrder = WorkOrderService.GetWorkOrder(innerWallOrder.BpsTaskId);
                        if (workOrder == null)
                        {
                            return ApiResult.Error($"{innerWallOrder.BpsTaskId}内墙工单不存在");
                        }
                        var uploadResult = await WorkOrderService.Upload(new UploadRequestDto
                        {
                            BpsTaskId = innerWallOrder.BpsTaskId,
                            StartTime = DateTime.Now,
                            EndTime = DateTime.Now,
                            JsonFile = staticFileBaseUrl + "InnerWallResult/json_FMS/output.json",
                            RobotCode = workOrder.ProcedureCode,
                            Version = fmsProjectInfo.UploadVersion,
                            Remark = "测量机器人上传",
                            Status = fmsProjectInfo.WorkOrderStatus
                        });
                        if (uploadResult.Code != AjaxCode.Success)
                        {
                            return ApiResult.Error($"上传内墙工单失败，详细信息：{uploadResult.Message}");
                        }
                    }
                    else// 无工单则自己上传机器人数据
                    {
                        FmsAlgorithmApiRspDto<string> fmsRsp = null;
                        if (request.InnerWallVersion == "1.3")
                            fmsRsp = await ProjectDCService.SaveInnerWallVisionCollectV1_3(rq);
                        else
                            fmsRsp = await ProjectDCService.SaveInnerWallVisionCollectV1_2(rq);
                        if (fmsRsp == null || fmsRsp.Code != 0)
                        {
                            Logger.Error($"UploadAlgorithmResultToFms：{JsonConvert.SerializeObject(rq)} {fmsRsp?.Message}");
                            return ApiResult.Error($"内墙数据上传失败，详细信息：{fmsRsp?.Message} ");
                        }
                    }
                }
                if (request.RobotCategoryList.Contains(WorkOrderTaskTypeEnum.螺杆洞.ToString()))
                {
                    string url = baseDir + "HolesResult/3Dholes.json";
                    string pngUrl = staticFileBaseUrl + "HolesResult/";
                    if (!File.Exists(url))
                    {
                        return ApiResult.Error("螺杆洞结果文件不存在");
                    }
                    var rspStr = await FileInfoUtils.ReadFileToStringAsync(url, Encoding.UTF8);
                    var holeJsonObj = JsonConvert.DeserializeObject<SaveSrowHoleVisionCollectRqDto>(rspStr);

                    holeJsonObj.BimMapCode = bimMapCode;
                    holeJsonObj.WallsPng?.ForEach(x =>
                    {
                        x.Url = pngUrl + x.Url;
                    });
                    holeJsonObj.Version = fmsProjectInfo.UploadVersion;
                    // 保存输出文件
                    string saveFilePath = baseDir + "HolesResult/output.json";
                    FileInfoUtils.SaveJsonFile(JsonConvert.SerializeObject(holeJsonObj), saveFilePath);
                    // 螺杆洞数据为空不上传
                    if (holeJsonObj.Holes == null || holeJsonObj.Holes.Count == 0)
                    {
                        Logger.Info($"UploadAlgorithmResultToFms：螺杆洞数据为空不上传{JsonConvert.SerializeObject(holeJsonObj)}");
                        return ApiResult.Success();
                    }
                    // 上传工单信息
                    var scrowHoleOrder = workOrderList.FirstOrDefault(x => x.ProcedureCode == WorkOrderCodeAndNameMap.GetProcedureCode(WorkOrderTaskTypeEnum.螺杆洞));
                    if (scrowHoleOrder != null)
                    {
                        var workOrder = WorkOrderService.GetWorkOrder(scrowHoleOrder.BpsTaskId);
                        if (workOrder == null)
                        {
                            return ApiResult.Error($"螺杆洞工单不存在");
                        }
                        var uploadResult = await WorkOrderService.Upload(new UploadRequestDto
                        {
                            BpsTaskId = scrowHoleOrder.BpsTaskId,
                            StartTime = DateTime.Now,
                            EndTime = DateTime.Now,
                            JsonFile = staticFileBaseUrl + "HolesResult/output.json",
                            RobotCode = workOrder.ProcedureCode,
                            Version = fmsProjectInfo.UploadVersion,
                            Remark = "测量机器人上传",
                            Status = fmsProjectInfo.WorkOrderStatus
                        });
                        if (uploadResult.Code != AjaxCode.Success)
                        {
                            return ApiResult.Error($"上传螺杆洞工单错误：{uploadResult.Message}");
                        }
                    }
                    else// 无工单则自己上传机器人数据
                    {
                        var fmsRsp = await ProjectDCService.SaveScrewHoleVisionCollect(holeJsonObj);
                        if (fmsRsp == null || fmsRsp.Code != 0)
                        {
                            Logger.Error($"UploadAlgorithmResultToFms：{JsonConvert.SerializeObject(holeJsonObj)} {fmsRsp?.Message}");
                            return ApiResult.Error($"螺杆洞数据上传失败，详细信息：{fmsRsp?.Message} ");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("UploadAlgorithmResultToFms", ex);
                return ApiResult.Error($"上传出错，详细信息：{ex.Message}");
            }
            return ApiResult.Success();
        }
    }
}